home *** CD-ROM | disk | FTP | other *** search
/ PC Media 23 / PC MEDIA CD23.iso / share / prog / newmat / myexcept.cpp < prev    next >
C/C++ Source or Header  |  1995-01-17  |  9KB  |  320 lines

  1. //$$except.cpp                        Exception handler
  2.  
  3. // Copyright (C) 1993,4: R B Davies
  4.  
  5.  
  6. #define WANT_STREAM                  // include.h will get stream fns
  7.  
  8.  
  9. #include "include.h"                 // include standard files
  10. #include "boolean.h"
  11.  
  12.  
  13. #include "myexcept.h"                  // for exception handling
  14.  
  15. //#define REG_DEREG                    // for print out uses of new/delete
  16. //#define CLEAN_LIST                   // to print entries being added to
  17.                                        // or deleted from cleanup list
  18.  
  19. #ifdef SimulateExceptions
  20.  
  21. void Throw()
  22. {
  23.    for (Janitor* jan = JumpBase::jl->janitor; jan; jan = jan->NextJanitor)
  24.       jan->CleanUp();
  25.    JumpBase::jl = JumpBase::jl->ji;
  26.    if ( ! JumpBase::jl ) Terminate();
  27.    Exception::last = JumpBase::jl->trace;
  28.    longjmp(JumpBase::jl->env, 1);
  29. }
  30.  
  31. void Throw(const Exception& exc) { JumpBase::type = exc.type(); Throw(); }
  32.  
  33. #endif                               // end of simulate exceptions
  34.  
  35.  
  36. void Exception::PrintTrace(Boolean)
  37. {
  38.     cout << "\n";
  39.    {
  40.         for (Tracer* et = last; et; et=et->previous)
  41.         cout << "  * " << et->entry << "\n";
  42.    }
  43. }
  44.  
  45. Exception::Exception(int action)
  46. {
  47.    if (action)
  48.    {
  49.       cout << "\nAn exception has occurred: call trace follows.";
  50.       PrintTrace();
  51.       if (action < 0) exit(1);
  52.    }
  53. }
  54.  
  55.  
  56. #ifdef SimulateExceptions
  57.  
  58.  
  59. Janitor::Janitor()
  60. {
  61.    if (do_not_link)
  62. //   if (do_not_link || !JumpBase::jl)      // second term is for global
  63.                                           // declarations when the JumpItem
  64.                                           // list might be empty
  65.    {
  66.       do_not_link = FALSE; NextJanitor = 0; OnStack = FALSE;
  67. #ifdef CLEAN_LIST
  68.       cout << "Not added to clean-list " << (unsigned long)this << "\n";
  69. #endif
  70.    }
  71.    else
  72.    {
  73.       OnStack = TRUE;
  74. #ifdef CLEAN_LIST
  75.       cout << "Add to       clean-list " << (unsigned long)this << "\n";
  76. #endif
  77.       NextJanitor = JumpBase::jl->janitor; JumpBase::jl->janitor=this;
  78.    }
  79. }
  80.  
  81. Janitor::~Janitor()
  82. {
  83.    // expect the item to be deleted to be first on list
  84.    // but must be prepared to search list
  85.    if (OnStack)
  86.    {
  87. #ifdef CLEAN_LIST
  88.       cout << "Delete from  clean-list " << (unsigned long)this << "\n";
  89. #endif
  90.       Janitor* lastjan = JumpBase::jl->janitor;
  91.       if (this == lastjan) JumpBase::jl->janitor = NextJanitor;
  92.       else
  93.       {
  94.      for (Janitor* jan = lastjan->NextJanitor; jan;
  95.         jan = lastjan->NextJanitor)
  96.      {
  97.         if (jan==this)
  98.            { lastjan->NextJanitor = jan->NextJanitor; return; }
  99.         lastjan=jan;
  100.      }
  101.  
  102.          cout << "\nCannot resolve memory linked list\n";
  103.          cout << "See notes in except.cpp for details\n";
  104.      Throw(Exception(-1));
  105. /*
  106. This message occurs when a call to ~Janitor() occurs, apparently without
  107. a corresponding call to Janitor(). This could happen if my way of
  108. deciding whether a constructor is being called by new fails. It can also
  109. happen if you have a class derived from Janitor which does not include a
  110. copy constructor [ eg X(const &X) ]. Possibly also if delete is applied
  111. an object on the stack (ie not called by new). Otherwise, it is a bug in
  112. Newmat or your compiler. If you don't #define TEMPS_DESTROYED_QUICKLY
  113. you will get this error with Microsoft C 7.0. There are probably
  114. situations where you will get this when you do define
  115. TEMPS_DESTROYED_QUICKLY. This is a bug in MSC. Beware of "operator"
  116. statements for defining conversions; particularly for converting from a
  117. Base class to a Derived class. 
  118.  
  119. You may get away with simply deleting this error message and Throw statement
  120. if you can't find a better way of overcoming the problem. In any case please
  121. tell me if you get this error message, particularly for compilers apart from
  122. Microsoft C.
  123. */
  124.       }
  125.    }
  126. }
  127.  
  128. JumpItem* JumpBase::jl;              // will be set to zero
  129. long JumpBase::type;
  130. jmp_buf JumpBase::env;
  131. Boolean Janitor::do_not_link;        // will be set to FALSE
  132.  
  133.  
  134. // static JumpItem JI;                  // need JumpItem at head of list
  135.  
  136.  
  137.  
  138. int JanitorInitializer::ref_count;
  139.  
  140. JanitorInitializer::JanitorInitializer()
  141. {
  142.    if (ref_count++ == 0)
  143.    {
  144.       new JumpItem;                 // need JumpItem at head of list
  145.    }
  146. }
  147.  
  148. #endif                            // end of SimulateExceptions
  149.  
  150. Tracer* Exception::last;             // will be set to zero
  151.  
  152.  
  153. void Terminate()
  154. {
  155.    cout << "\nThere has been an exception with no handler - exiting\n";
  156.    exit(1);
  157. }
  158.  
  159.  
  160.  
  161. #ifdef DO_FREE_CHECK
  162. // Routines for tracing whether new and delete calls are balanced
  163.  
  164. FreeCheckLink::FreeCheckLink() : next(FreeCheck::next)
  165.    { FreeCheck::next = this; }
  166.  
  167. FCLClass::FCLClass(void* t, char* name) : ClassName(name) { ClassStore=t; }
  168.  
  169. FCLRealArray::FCLRealArray(void* t, char* o, int s)
  170.   : Operation(o), size(s) { ClassStore=t; }
  171.  
  172. FCLIntArray::FCLIntArray(void* t, char* o, int s)
  173.   : Operation(o), size(s) { ClassStore=t; }
  174.  
  175. FreeCheckLink* FreeCheck::next;
  176. int FreeCheck::BadDelete;
  177.  
  178. void FCLClass::Report()
  179. { cout << "   " << ClassName << "   " << (unsigned long)ClassStore << "\n"; }
  180.  
  181. void FCLRealArray::Report()
  182. {
  183.    cout << "   " << Operation << "   " << (unsigned long)ClassStore << 
  184.       "   " << size << "\n";
  185. }
  186.  
  187. void FCLIntArray::Report()
  188. {
  189.    cout << "   " << Operation << "   " << (unsigned long)ClassStore << 
  190.       "   " << size << "\n";
  191. }
  192.  
  193. void FreeCheck::Register(void* t, char* name)
  194. {
  195.    FCLClass* f = new FCLClass(t,name);
  196.    if (!f) { cout << "Out of memory in FreeCheck\n"; exit(1); }
  197. #ifdef REG_DEREG
  198.    cout << "Registering   " << name << "   " << (unsigned long)t << "\n";
  199. #endif
  200. }
  201.  
  202. void FreeCheck::RegisterR(void* t, char* o, int s)
  203. {
  204.    FCLRealArray* f = new FCLRealArray(t,o,s);
  205.    if (!f) { cout << "Out of memory in FreeCheck\n"; exit(1); }
  206. #ifdef REG_DEREG
  207.    cout << o << "   " << s << "   " << (unsigned long)t << "\n";
  208. #endif
  209. }
  210.  
  211. void FreeCheck::RegisterI(void* t, char* o, int s)
  212. {
  213.    FCLIntArray* f = new FCLIntArray(t,o,s);
  214.    if (!f) { cout << "Out of memory in FreeCheck\n"; exit(1); }
  215. #ifdef REG_DEREG
  216.    cout << o << "   " << s << "   " << (unsigned long)t << "\n";
  217. #endif
  218. }
  219.  
  220. void FreeCheck::DeRegister(void* t, char* name)
  221. {
  222.    FreeCheckLink* last = 0;
  223. #ifdef REG_DEREG
  224.    cout << "Deregistering " << name << "   " << (unsigned long)t << "\n";
  225. #endif
  226.    for (FreeCheckLink* fcl = next; fcl; fcl = fcl->next)
  227.    {
  228.       if (fcl->ClassStore==t)
  229.       {
  230.      if (last) last->next = fcl->next; else next = fcl->next;
  231.      delete fcl; return;
  232.       }
  233.       last = fcl;
  234.    }
  235.    cout << "\nRequest to delete non-existent object of class and location:\n";
  236.    cout << "   " << name << "   " << (unsigned long)t << "\n";
  237.    BadDelete++;
  238.    Exception::PrintTrace(TRUE);
  239.    cout << "\n";
  240. }
  241.  
  242. void FreeCheck::DeRegisterR(void* t, char* o, int s)
  243. {
  244.    FreeCheckLink* last = 0;
  245. #ifdef REG_DEREG
  246.    cout << o << "   " << s << "   " << (unsigned long)t << "\n";
  247. #endif
  248.    for (FreeCheckLink* fcl = next; fcl; fcl = fcl->next)
  249.    {
  250.       if (fcl->ClassStore==t)
  251.       {
  252.      if (last) last->next = fcl->next; else next = fcl->next;
  253.      if (((FCLRealArray*)fcl)->size != s)
  254.      {
  255.         cout << "\nArray sizes don't agree:\n";
  256.         cout << "   " << o << "   " << (unsigned long)t
  257.            << "   " << s << "\n";
  258.         Exception::PrintTrace(TRUE);
  259.         cout << "\n";
  260.      }
  261.      delete fcl; return;
  262.       }
  263.       last = fcl;
  264.    }
  265.    cout << "\nRequest to delete non-existent real array:\n";
  266.    cout << "   " << o << "   " << (unsigned long)t << "   " << s << "\n";
  267.    BadDelete++;
  268.    Exception::PrintTrace(TRUE);
  269.    cout << "\n";
  270. }
  271.  
  272. void FreeCheck::DeRegisterI(void* t, char* o, int s)
  273. {
  274.    FreeCheckLink* last = 0;
  275. #ifdef REG_DEREG
  276.    cout << o << "   " << s << "   " << (unsigned long)t << "\n";
  277. #endif
  278.    for (FreeCheckLink* fcl = next; fcl; fcl = fcl->next)
  279.    {
  280.       if (fcl->ClassStore==t)
  281.       {
  282.      if (last) last->next = fcl->next; else next = fcl->next;
  283.      if (((FCLIntArray*)fcl)->size != s)
  284.      {
  285.         cout << "\nArray sizes don't agree:\n";
  286.         cout << "   " << o << "   " << (unsigned long)t
  287.            << "   " << s << "\n";
  288.         Exception::PrintTrace(TRUE);
  289.         cout << "\n";
  290.      }
  291.      delete fcl; return;
  292.       }
  293.       last = fcl;
  294.    }
  295.    cout << "\nRequest to delete non-existent int array:\n";
  296.    cout << "   " << o << "   " << (unsigned long)t << "   " << s << "\n";
  297.    BadDelete++;
  298.    Exception::PrintTrace(TRUE);
  299.    cout << "\n";
  300. }
  301.  
  302. void FreeCheck::Status()
  303. {
  304.    if (next)
  305.    {
  306.       cout << "\nObjects of the following classes remain undeleted:\n";
  307.       for (FreeCheckLink* fcl = next; fcl; fcl = fcl->next) fcl->Report();
  308.       cout << "\n";
  309.    }
  310.    else cout << "\nNo objects remain undeleted\n\n";
  311.    if (BadDelete)
  312.    {
  313.       cout << "\nThere were " << BadDelete << 
  314.          " requests to delete non-existent items\n\n";
  315.    }
  316. }
  317.  
  318. #endif
  319.  
  320.